﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Text;
using System.Security.Principal;
using GwLib.JqGridMvc.Extensions;

namespace GwLib.JqGridMvc
{
    public class JqGridActionUrls
    {
        public string DataSource { get; set; }
    }

    public static class JqGridExtensions
    {

        /// <summary>
        /// Renders the HTML needed for the MainMenu.
        /// </summary>
        /// <param name="htmlHelper">The HTML helper.</param>
        /// <returns></returns>
        public static MvcHtmlString RenderJqGrid(this HtmlHelper htmlHelper, JqGrid grid, JqGridActionUrls actionUrls, bool writeScriptTags = false)
        {
            StringBuilder html = new StringBuilder();
            int i;

            // Render the HTML for the JqGrid
            if (writeScriptTags)
            {
                html.AppendLine("<script type=\"text/javascript\">");
            }

            if (grid.IsCellEditingEnabled.HasValue)
            {
                if (grid.IsCellEditingEnabled.Value)
                {
                    html.AppendLine("var lastsel;");
                }
            }

            html.AppendLine("$().ready(function () {")
                .Append("\t").Append("$(").AppendJs(grid.JQuerySelector).AppendLine(").jqGrid( {");

            if (!string.IsNullOrEmpty(grid.LoadCompleteFunction))
            {
                html.AppendTabs(2).Append("loadComplete: ").Append(grid.LoadCompleteFunction).AppendLine(",");
            }
            if (!string.IsNullOrEmpty(grid.LoadErrorFunction))
            {
                html.AppendTabs(2).Append("loadError: ").Append(grid.LoadErrorFunction).AppendLine(",");
            }
            if (!string.IsNullOrEmpty(grid.GridCompleteFunction))
            {
                html.AppendTabs(2).Append("gridComplete: ").Append(grid.GridCompleteFunction).AppendLine(",");
            }
            if (!string.IsNullOrEmpty(grid.DoubleClickRowFunction))
            {
                html.AppendTabs(2).Append("ondblClickRow: ").Append(grid.DoubleClickRowFunction).AppendLine(",");
            }

            if (!string.IsNullOrEmpty(actionUrls.DataSource))
            {
                html.AppendTabs(2).Append("url: ").AppendJs(actionUrls.DataSource).AppendLine(",");
            }
            else if (!string.IsNullOrEmpty(grid.DataSource.Url))
            {
                html.AppendTabs(2).Append("url: ").AppendJs(grid.DataSource.Url).AppendLine(",");
            }

            string dataType = grid.DataSource.DataType.ToString().ToLower();
            if (!(grid.PerformSearchOnLoad ?? true))
            {
                dataType = "local";
            }
            html.AppendTabs(2).Append("datatype: ").AppendJs(dataType).AppendLine(",");

            // Column Headers
            html.AppendTabs(2).AppendLine("colNames: [")
                .AppendTabs(3);
            i = 0;
            foreach (JqGridColumn col in grid.Columns) 
            {
                if (i > 0) html.Append(", ");
                html.AppendJs(col.HeaderCaption);
                i++;
            }
            html.AppendLine()
                .AppendTabs(2).AppendLine("],");

            // Column Definition
            html.AppendTabs(2).AppendLine("colModel: [")
                ;
            i = 0;
            foreach (JqGridColumn col in grid.Columns)
            {
                if (i > 0) html.AppendLine(",");
                html.AppendTabs(3)
                    .Append("{");

                bool first = true;
                if (!string.IsNullOrWhiteSpace(col.Name))
                {
                    html.Append(first ? string.Empty : ",").Append("name: ").AppendJs(col.Name);
                    first = false;
                }
                if (!string.IsNullOrWhiteSpace(col.DataSourceFieldName))
                {
                    html.Append(first ? string.Empty : ",").Append("index: ").AppendJs(col.Name);
                    first = false;
                }
                if (!string.IsNullOrWhiteSpace(col.DateFormatString))
                {
                    html.Append(first ? string.Empty : ",").Append("datefmt: ").AppendJs(col.DateFormatString);
                    first = false;
                }
                if (!string.IsNullOrWhiteSpace(col.CellAttributesFunctionName))
                {
                    html.Append(first ? string.Empty : ",").Append("cellattr: ").Append(col.CellAttributesFunctionName);
                    first = false;
                }
                if (col.Width.HasValue)
                {
                    html.Append(first ? string.Empty : ",").Append("width: ").Append(col.Width);
                    first = false;
                }
                if (col.Alignment.HasValue)
                {
                    html.Append(first ? string.Empty : ",").Append("align: ").AppendJs(col.Alignment.Value.ToString().ToLower());
                    first = false;
                }
                if (col.IsSortable.HasValue)
                {
                    html.Append(first ? string.Empty : ",").Append("sortable: ").AppendJs(col.IsSortable);
                    first = false;
                }
                if (col.IsHidden.HasValue)
                {
                    html.Append(first ? string.Empty : ",").Append("hidden: ").AppendJs(col.IsHidden);
                    first = false;
                }
                if (col.IsSearchable.HasValue)
                {
                    html.Append(first ? string.Empty : ",").Append("search: ").AppendJs(col.IsSearchable);
                    first = false;
                }
                if (col.IsKey.HasValue)
                {
                    html.Append(first ? string.Empty : ",").Append("key: ").AppendJs(col.IsKey);
                    first = false;
                }
                if (col.IsEditable.HasValue)
                {
                    html.Append(first ? string.Empty : ",").Append("editable: ").AppendJs(col.IsEditable);
                    first = false;
                }
                if (col.EditType.HasValue)
                {
                    html.Append(first ? string.Empty : ",").Append("edittype: ");
                    switch (col.EditType.Value)
                    {
                        case JqGridColumnEditType.CheckBox:
                            html.AppendJs("checkbox");
                            break;
                        default:
                            html.AppendJs("text");
                            break;
                    }
                    first = false;
                }
                if (!string.IsNullOrWhiteSpace(col.EditOptions)) //TODO: need to make this an object model!
                {
                    html.Append(first ? string.Empty : ",").Append("editoptions: ").Append(col.EditOptions);
                    first = false;
                }
                if (!string.IsNullOrWhiteSpace(col.FormatOptions)) //TODO: need to make this an object model!
                {
                    html.Append(first ? string.Empty : ",").Append("formatoptions: ").Append(col.FormatOptions);
                    first = false;
                }
                if (!string.IsNullOrWhiteSpace(col.FormatExtensionName))
                {
                    html.Append(first ? string.Empty : ",").Append("formatter: ").AppendJs(col.FormatExtensionName);
                    first = false;
                }
                else if (!string.IsNullOrWhiteSpace(col.FormatFunctionName))
                {
                    html.Append(first ? string.Empty : ",").Append("formatter: ").Append(col.FormatFunctionName);
                    first = false;
                }
                if (!string.IsNullOrWhiteSpace(col.UnformatFunctionName))
                {
                    html.Append(first ? string.Empty : ",").Append("unformat: ").Append(col.UnformatFunctionName);
                    first = false;
                }
                if (!string.IsNullOrWhiteSpace(col.EditOptions))
                {
                    html.Append(first ? string.Empty : ",").Append("editoptions: ").Append(col.EditOptions);
                    first = false;
                }
                if (col.IsEditable.HasValue)
                {
                    html.Append(first ? string.Empty : ",").Append("editable: ").AppendJs(col.IsEditable);
                    first = false;
                }
                /*
                               EditType = JqGridColumnEditType.CheckBox,
                               EditOptions  = "{value:\"true:false\"}",*/

                if (!col.IsSearchable.HasValue || col.IsSearchable.Value)
                {
                    //sOper = 'cn'
                    //sopt = ['eq','ne','lt','le','gt','ge','bw','bn','in','ni','ew','en','cn','nc'] 
                    html.Append(first ? string.Empty : ",").Append("searchoptions: {sopt: ['cn', 'eq', 'bw', 'ew', 'nu']}");
                    first = false;
                }

                html.Append("}");
                i++;
            }
            html.AppendLine()
                .AppendTabs(2).AppendLine("],");

/*beforeSelectRow: function (rowid, e) {
    return false;
}*/
            if (!(grid.IsRowSelectionEnabled ?? false))
            {
                    html.AppendLine()
                        .AppendTabs(2).AppendLine(
@"beforeSelectRow: function(rowid, e) {
		return false;
	},");
            }
            // Other properties
            else if (grid.IsCellEditingEnabled.HasValue)
            {
                //editurl:"someurl.php",
                if (grid.IsCellEditingEnabled.Value)
                {
                    html.AppendLine()
                        .AppendTabs(2).AppendLine(
@"onSelectRow: function(id) {
		if(id && id!==lastsel) {
			jQuery('#rowed3').jqGrid('restoreRow',lastsel);
			jQuery('#rowed3').jqGrid('editRow',id,true);
			lastsel=id;
		}
	},");
                }
                /*,
	onSelectRow: function(id){
		if(id && id!==lastsel){
			jQuery('#rowed3').jqGrid('restoreRow',lastsel);
			jQuery('#rowed3').jqGrid('editRow',id,true);
			lastsel=id;
		}
	},*/
            }

            if (!string.IsNullOrWhiteSpace(grid.EditUrl))
            {
                html.AppendTabs(2).Append("editurl: ").AppendJs(grid.EditUrl).AppendLine(",");
            }
            if (grid.ViewableRowCount.HasValue)
            {
                html.AppendTabs(2).Append("rowNum: ").Append(grid.ViewableRowCount.Value).AppendLine(",");
            }
            if (grid.IsInitialWidthAutomatic.HasValue)
            {
                html.AppendTabs(2).Append("autowidth: ").AppendJs(grid.IsInitialWidthAutomatic).AppendLine(",");
            }
            if (!string.IsNullOrWhiteSpace(grid.DefaultSortColumnName))
            {
                html.AppendTabs(2).Append("sortname: ").AppendJs(grid.DefaultSortColumnName).AppendLine(",");
            }
            if (grid.DefaultSortAscending.HasValue)
            {
                html.AppendTabs(2).Append("sortorder: ").AppendJs(grid.DefaultSortAscending.Value ? "asc" : "desc").AppendLine(",");
            }

            if (grid.HeightType == JqGridHeightType.Pixel && grid.Height.HasValue)
            {
                html.AppendTabs(2).Append("height: ").Append(grid.Height).AppendLine(",");
            }
            else if (grid.HeightType == JqGridHeightType.Percent100)
            {
                html.AppendTabs(2).AppendLine("height: \"100%\",");
            }
            else if (grid.HeightType == JqGridHeightType.Auto)
            {
                html.AppendTabs(2).AppendLine("height: \"auto\",");
            }
            else if (grid.HeightType == JqGridHeightType.Custom)
            {
                if (!string.IsNullOrWhiteSpace(grid.CustomHeightTypeExpression))
                    html.AppendTabs(2).Append("height: ").Append(grid.CustomHeightTypeExpression).AppendLine(",");
            }

            bool pagingEnabled = grid.Paging.Enabled && !string.IsNullOrWhiteSpace(grid.Paging.JQuerySelector);

            if (pagingEnabled)
            {
                html.AppendTabs(2).Append("pager: $(").AppendJs(grid.Paging.JQuerySelector).AppendLine("),");
                if (grid.Paging.RecordsPerPageCountOptions != null)
                {
                    html.AppendTabs(2).Append("rowList: ").AppendJs(grid.Paging.RecordsPerPageCountOptions).AppendLine(",");
                }
                if (grid.Paging.ViewRecordCountInfo.HasValue)
                {
                    html.AppendTabs(2).Append("viewrecords: ").AppendJs(grid.Paging.ViewRecordCountInfo).AppendLine(",");
                }
            }

            html.AppendTabs(2).Append("caption: ").AppendJs(grid.Caption).AppendLine("");


            html.AppendTabs(1).AppendLine("})");

            if (pagingEnabled)
            {
                html.AppendTabs(1)
                    .Append(".navGrid(")
                    .AppendJs(grid.Paging.JQuerySelector);

                if (grid.IsCellEditingEnabled.HasValue && grid.IsCellEditingEnabled.Value)
                {
                    //TODO: Build model around grid editing options
                    html.Append(@", {},
{reloadAfterSubmit:false},
{reloadAfterSubmit:false}, 
{reloadAfterSubmit:false},
{}
");
                }
                else
                {
                    html.Append(", {edit:false,add:false,del:false,search:")
                        .AppendJs(grid.IsSingleSearchEnabled ?? true)
                        .Append(",refresh:")
                        .AppendJs(grid.IsRefreshEnabled ?? true).Append("}");
                }
                html.Append(");")

                .AppendLine();

            }

            if (!(grid.PerformSearchOnLoad ?? true))
            {
                html.Append("\t").Append("$(").AppendJs(grid.JQuerySelector).Append(").jqGrid('setGridParam', { datatype: '")
                    .Append(grid.DataSource.DataType.ToString().ToLower()).AppendLine("'});");
            }
            html.AppendLine("});");
            /*
        //if (me.dataSourceDataType != null)
        //    me.$gridElement.jqGrid('setGridParam', { datatype: 'json' });*/
            if (writeScriptTags)
            {
                html.AppendLine("</script>");
            }

            return MvcHtmlString.Create(html.ToString());
        }
    }
}